package io.renren.modules.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.renren.common.config.BaseConstant;
import io.renren.common.enums.ErrorCode;
import io.renren.common.exception.RRException;
import io.renren.common.utils.AliOSSComponent;
import io.renren.common.utils.CheckParam;
import io.renren.common.utils.SnowflakeIdWorker;
import io.renren.modules.app.req.weixin.WeChatGetUserInfoReq;
import io.renren.modules.app.req.weixin.WeChatLoginReq;
import io.renren.modules.app.service.WeChatLoginService;
import io.renren.modules.app.vo.weixin.AppRiderLoginResp;
import io.renren.modules.app.vo.weixin.AppUserResp;
import io.renren.modules.app.vo.weixin.MerchantLoginResp;
import io.renren.modules.app.vo.weixin.WxResp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.shiro.codec.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigDecimal;
import java.net.URI;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.time.Instant;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author create by jieshao email:2609207540@qq.com
 * @projectName house-club-api
 * @Description: 商户微信登录相关服务方法实现
 * @date 2020-04-15
 */
@Service("weChatLoginService")
@Slf4j
public class WeChatLoginServiceImpl implements WeChatLoginService {

    @Resource
    private BaseConstant baseConstant;

    @Resource
    private AliOSSComponent aliOSSComponent;

    @Override
    public WxResp login(WeChatLoginReq weChatLoginReq) {

        // 创建Httpclient对象
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String resultString = "";
        String appId = "";
        String appSecret = "";
        CloseableHttpResponse response = null;
        if (CheckParam.isNull(weChatLoginReq.getStatus())) {
            throw new RRException(ErrorCode.NO_REQUIRED_PARAM_ERROR.getMessage(),ErrorCode.NO_REQUIRED_PARAM_ERROR.getCode());
        }
        if (weChatLoginReq.getStatus() == 1) {
            appId = baseConstant.getUserAppId();
            appSecret = baseConstant.getUserAppSecret();
        }
        if (weChatLoginReq.getStatus() == 2) {
            appId = baseConstant.getAppId();
            appSecret = baseConstant.getAppSecret();
        }
        if (weChatLoginReq.getStatus() == 3) {
            appId = baseConstant.getRiderAppId();
            appSecret = baseConstant.getRiderAppSecret();
        }

        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + appSecret + "&js_code=" + weChatLoginReq.getCode() + "&grant_type=authorization_code";
        try {
            // 创建url
            URIBuilder builder = new URIBuilder(url);
            URI uri = builder.build();

            // 创建http GET请求
            HttpGet httpGet = new HttpGet(uri);

            // 执行请求
            response = httpclient.execute(httpGet);
            // 判断返回状态是否为200
            if (response.getStatusLine().getStatusCode() == 200) {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 解析json
        JSONObject jsonObject = (JSONObject) JSONObject.parse(resultString);
        WxResp wxResp = new WxResp();
        wxResp.setOpenId(jsonObject.get("openid").toString());
        wxResp.setSessionKey(jsonObject.get("session_key").toString());


        log.info("================[用户登录]session_key:{}  结果为:{}", jsonObject.get("session_key").toString());
        log.info("================[用户登录]openid:{}  结果为:{}", jsonObject.get("openid").toString());


        return wxResp;
    }


    /**
     * 解密用户敏感数据获取用户信息
     *
     * @param weChatGetUserInfoReq 数据进行加密签名的密钥   包括敏感数据在内的完整用户信息的加密数据  加密算法的初始向量
     * @param
     * @param
     */
    @Override
    public AppUserResp getUserInfo(WeChatGetUserInfoReq weChatGetUserInfoReq) {

        Map<String, Object> parse = weChatLogin(weChatGetUserInfoReq);
        AppUserResp appUserResp = new AppUserResp();
        appUserResp.setOpenId(parse.get("openId").toString());
        appUserResp.setCity(parse.get("city").toString());
        appUserResp.setNickName(parse.get("nickName").toString());
        appUserResp.setSessionKey(weChatGetUserInfoReq.getSessionKey());
        appUserResp.setCountry(parse.get("country").toString());
        appUserResp.setProvince(parse.get("province").toString());
        try {
            appUserResp.setHeadImg(aliOSSComponent.getObjectAccessUrl(parse.get("avatarUrl").toString()));
        } catch (Exception e) {
            e.printStackTrace();
        }

        appUserResp.setUserStatus(1);
        appUserResp.setGender(Integer.valueOf(parse.get("gender").toString()));


        //更新登陆时间为当前的时间
        appUserResp.setLastLogin(Date.from(Instant.now()));
        //设置登陆次数+1
        if (appUserResp.getLoginAcc() == null) {
            appUserResp.setLoginAcc(0);
        }
        appUserResp.setLoginAcc(appUserResp.getLoginAcc() + 1);


        //生成token
        String authToken = SnowflakeIdWorker.uniqueSequenceStr();

        String authUserPrefix = baseConstant.getAppAuthTokenPrefix() + "." + authToken;
        appUserResp.setToken(authToken);
        appUserResp.setVipFlag(1);

        //存储数据

//        AppUser appUser1 = appUserRepository.findByOpenId(appUserResp.getOpenId());
//        if (CheckParam.isNull(appUser1)) {
//            AppUser appUser = new AppUser();
//            //   appUser.setUserId(SnowflakeIdWorker.uniqueSequenceStr());
//            appUserResp.setUserId(appUser.getUserId());
//
//            redisRepository.set(authUserPrefix, JSON.toJSONString(appUserResp), Long.valueOf(baseConstant.getAppTokenExpiredTime()), TimeUnit.DAYS);
//            try {
//                BeanUtils.copyProperties(appUser, appUserResp);
//                appUser.setNickName(Base64.encodeToString(appUser.getNickName().getBytes("UTF-8")));
//                appUser.setHeadImg(parse.get("avatarUrl").toString());
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//            //初始化账户表
//            AppUserAccount appUserAccount = new AppUserAccount();
//            appUserAccount.setUserId(appUser.getUserId());
//            appUserAccount.setCashAcc(new BigDecimal(0));
//            appUserAccount.setIntegrateAcc(0);
//            appUserAccount.setVipFlag(1);
//            appUserAccount.setRechargeAmount(new BigDecimal(0));
//            appUserAccount.setWithdrawAmount(new BigDecimal(0));
//            appUserAccountRepository.insert(appUserAccount);
//            appUserRepository.insert(appUser);
//        } else {
//
//            appUser1.setLastLogin(Date.from(Instant.now()));
//            appUser1.setLoginAcc(appUser1.getLoginAcc() + 1);
//            appUserRepository.updateByPrimaryKeySelective(appUser1);
//            try {
//                BeanUtils.copyProperties(appUserResp, appUser1);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//            appUserResp.setNickName(parse.get("nickName").toString());
//            AppUserAccount userAccount = appUserAccountRepository.findUserAccount(appUser1.getUserId());
//            if (!CheckParam.isNull(userAccount)) {
//                appUserResp.setVipFlag(userAccount.getVipFlag());
//            }
//            redisRepository.set(authUserPrefix, JSON.toJSONString(appUserResp), Long.valueOf(baseConstant.getAppTokenExpiredTime()), TimeUnit.DAYS);
//        }

        return appUserResp;
    }


    @Override
    public AppRiderLoginResp getAndAddRiderInfo(WeChatGetUserInfoReq weChatGetUserInfoReq) {
        Map<String, Object> parse = weChatLogin(weChatGetUserInfoReq);
        AppRiderLoginResp appRiderLoginResp = new AppRiderLoginResp();

        appRiderLoginResp.setCity(parse.get("city").toString());
        appRiderLoginResp.setNickName(parse.get("nickName").toString());
        appRiderLoginResp.setOpenId(parse.get("openId").toString());
        appRiderLoginResp.setSessionKey(weChatGetUserInfoReq.getSessionKey());
        appRiderLoginResp.setCountry(parse.get("country").toString());
        appRiderLoginResp.setProvince(parse.get("province").toString());
        try {
            appRiderLoginResp.setHeadImg(aliOSSComponent.getObjectAccessUrl(parse.get("avatarUrl").toString()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        appRiderLoginResp.setGender(Integer.valueOf(parse.get("gender").toString()));


        //更新登陆时间为当前的时间
        appRiderLoginResp.setLastLogin(Date.from(Instant.now()));
        //设置登陆次数+1
        if (appRiderLoginResp.getLoginAcc() == null) {
            appRiderLoginResp.setLoginAcc(0);
        }
        appRiderLoginResp.setLoginAcc(appRiderLoginResp.getLoginAcc() + 1);


        //生成token
        String authToken = SnowflakeIdWorker.uniqueSequenceStr();

        String authUserPrefix = baseConstant.getAppAuthTokenPrefix() + "." + authToken;
        appRiderLoginResp.setToken(authToken);


        //存储数据
//        redisRepository.set(authUserPrefix, JSON.toJSONString(appRiderLoginResp), Long.valueOf(baseConstant.getAppTokenExpiredTime()), TimeUnit.DAYS);
//        AppRider appRider = new AppRider();
//        try {
//            BeanUtils.copyProperties(appRider, appRiderLoginResp);
//            appRider.setNickName(Base64.encodeToString(appRiderLoginResp.getNickName().getBytes("UTF-8")));
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        appRider.setRiderStatus(1);
//        AppRider byOpenId = appRiderRepository.findByOpenId(appRider.getOpenId());
//        if (byOpenId == null) {
//            appRiderRepository.insert(appRider);
//        }
           /* appRider.setId(byOpenId.getId());
            appRider.setLastLogin(Date.from(Instant.now()));
            appRiderRepository.updateByPrimaryKeySelective(appRider);*/


        return appRiderLoginResp;
    }

    @Override
    public MerchantLoginResp getAndAddMerchantInfo(WeChatGetUserInfoReq weChatGetUserInfoReq) {
        //获取微信登录数据
        Map<String, Object> parse = weChatLogin(weChatGetUserInfoReq);
        //初始化响应类
        MerchantLoginResp merchantLoginResp = new MerchantLoginResp();
        //设置响应类的信息
        merchantLoginResp.setCity(parse.get("city").toString());
        merchantLoginResp.setNickName(parse.get("nickName").toString());
        merchantLoginResp.setOpenId(parse.get("openId").toString());
        merchantLoginResp.setSessionKey(weChatGetUserInfoReq.getSessionKey());
        merchantLoginResp.setCountry(parse.get("country").toString());
        merchantLoginResp.setProvince(parse.get("province").toString());
        try {
            //返回图片信息
            merchantLoginResp.setHeadImg(aliOSSComponent.getObjectAccessUrl(parse.get("avatarUrl").toString()));
        } catch (Exception e) {
            e.printStackTrace();
        }

        merchantLoginResp.setGender(Integer.valueOf(parse.get("gender").toString()));

        //生成token
        String authToken = SnowflakeIdWorker.uniqueSequenceStr();
        String authUserPrefix = baseConstant.getAppAuthTokenPrefix() + "." + authToken;

//        redisRepository.set(authUserPrefix, authToken, Long.valueOf(baseConstant.getAppTokenExpiredTime()), TimeUnit.DAYS);
//        merchantLoginResp.setToken(authToken);
//
//        redisRepository.set(authUserPrefix, JSON.toJSONString(merchantLoginResp), Long.valueOf(baseConstant.getAppTokenExpiredTime()), TimeUnit.DAYS);
//
//        AppMerchant appMerchant = new AppMerchant();
//        try {
//            BeanUtils.copyProperties(appMerchant, merchantLoginResp);
//            appMerchant.setNickName(Base64.encodeToString(merchantLoginResp.getNickName().getBytes("UTF-8")));
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        appMerchant.setHeadImg(parse.get("avatarUrl").toString());
//        AppMerchant newMerchant = appMerchantRepository.findByOpenId(appMerchant.getOpenId());
//        if (newMerchant == null) {
//            appMerchant.setIsAuth(1);//未认证
//            appMerchantRepository.insert(appMerchant);
//            //初始化账户信息
//            MerchantAccount merchantAccount = new MerchantAccount();
//            merchantAccount.setMerchantId(appMerchant.getMerchantId());
//            merchantAccountRepository.insert(merchantAccount);
//        }

        return merchantLoginResp;
    }

    private Map<String, Object> weChatLogin(WeChatGetUserInfoReq weChatGetUserInfoReq) {

        if (CheckParam.isNull(weChatGetUserInfoReq)) {
            throw new RRException(ErrorCode.PARAM_ERROR.getMessage(),ErrorCode.ERROR.getCode());
        }
        // 被加密的数据
        byte[] dataByte = Base64.decode(weChatGetUserInfoReq.getEncryptedData());
        // 加密秘钥
        byte[] keyByte = Base64.decode(weChatGetUserInfoReq.getSessionKey());
        // 偏移量
        byte[] ivByte = Base64.decode(weChatGetUserInfoReq.getIv());
        Map<String, Object> parse = null;
        try {
            // 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, "UTF-8");
                parse = (Map<String, Object>) JSON.parse(result);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return parse;
    }

}
